import threading

import cv2
import time

from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5.QtGui import QImage, QPixmap, QCursor
from ui.video_ui import video_ui


class video_thrad(QThread):
    signal = pyqtSignal(list)
    threadLock = threading.Lock()

    label = None
    capture = None

    run_flag = True
    pause_flag = False
    width = 0
    hight = 0

    frame = None
    rects = []
    now_rect = None
    linecoor = None
    fps = 0
    video_mode = True

    def __init__(self, admin):
        super().__init__()
        self.admin = admin

    def run(self):
        while self.run_flag:
            if self.pause_flag is False:
                self.loop()
        self.run_flag = True

    def exit_run(self):
        if self.run_flag is True:
            self.run_flag = False
        while self.run_flag is False:
            pass

    def pause_run(self, flag):
        self.pause_flag = flag

    def set_label(self, label):
        self.label = label

    def set_capture(self, path_name):
        if path_name.isdigit():
            self.capture = cv2.VideoCapture(int(path_name))
            self.video_mode = False
        else:
            self.capture = cv2.VideoCapture(path_name)
            self.video_mode = True
        self.width = int(self.capture.get(cv2.CAP_PROP_FRAME_WIDTH))
        self.hight = int(self.capture.get(cv2.CAP_PROP_FRAME_HEIGHT))
        self.fps = self.capture.get(cv2.CAP_PROP_FPS)
        # 设置显示
        videoUI = self.admin.getUI(video_ui)
        videoUI.set_size(int(self.width), int(self.hight))
        videoUI.show()

        if self.video_mode:
            self.admin.getUI(video_ui).set_frame_num(self.capture.get(cv2.CAP_PROP_FRAME_COUNT))
        else:
            self.admin.getUI(video_ui).set_frame_num(0)

    def get_frame(self):
        frame = self.frame
        # self.frame = None
        return frame

    def set_frame_id(self, id):
        self.threadLock.acquire()
        if id != 0:
            id = id - 1
        self.capture.set(cv2.CAP_PROP_POS_FRAMES, id)
        self.threadLock.release()

    # 添加矩形到列表
    def addRect(self, x1, y1, x2, y2):
        self.rects.append([x1, y1, x2, y2])
        self.now_rect = None

    # 删除当前选择矩形
    def delRect(self):
        if self.now_rect is not None:
            self.now_rect = None

    # 从列表挑选矩形
    def get_nowRect(self, xn, yn):
        n = 3
        if self.now_rect is not None:
            self.rects.append(self.now_rect)
        for i in range(len(self.rects)):
            x1, y1, x2, y2 = self.rects[i]
            if (x1 - xn) ** 2 <= n * 2 or \
                    (x2 - xn) ** 2 <= n ** 2 or \
                    (y1 - yn) ** 2 <= n ** 2 or \
                    (y2 - yn) ** 2 <= n ** 2:
                self.now_rect = self.rects.pop(i)
                return True
        self.now_rect = None
        return False

    def resize_nowRect(self, zoom, mode=0):
        if self.now_rect is not None:
            x1, y1, x2, y2 = self.now_rect
            if mode == 0:
                x1 = x1 - zoom
                y1 = y1 - zoom
                x2 = x2 + zoom
                y2 = y2 + zoom
            elif mode == 1:
                x1 = x1 - zoom
                x2 = x2 + zoom
            elif mode == 2:
                y1 = y1 - zoom
                y2 = y2 + zoom
            self.now_rect = [x1, y1, x2, y2]

    # 设置当前矩形
    def set_nowRect(self, rect):
        self.now_rect = rect

    def move_nowRect(self, xoff, yoff):
        if self.now_rect is None:
            return
        x1, y1, x2, y2 = self.now_rect
        if x1 + xoff < 0:
            xoff = -x1
        if x2 + xoff > self.width:
            xoff = self.width - x2
        if y1 + yoff < 0:
            yoff = -y1
        if y2 + xoff > self.hight:
            yoff = self.hight - y2

        x1 = int(x1 + xoff)
        x2 = int(x2 + xoff)
        y1 = int(y1 + yoff)
        y2 = int(y2 + yoff)
        self.now_rect = [x1, y1, x2, y2]

    def set_linecoor(self, coor):
        if coor is not None:
            x = int(coor[0])
            y = int(coor[1])
            coor = [x, y]
        self.linecoor = coor

    def set_fps(self, multiple):
        if self.video_mode:
            fps = self.fps * multiple
            if fps < 0.4:
                return False
            if fps > 480:
                return False
            self.fps = fps
            return True

    def set_pause(self, flag):
        self.pause_flag = flag

    def last_frame(self):
        if self.video_mode:
            self.threadLock.acquire()
            index = self.capture.get(cv2.CAP_PROP_POS_FRAMES) - 2
            self.capture.set(cv2.CAP_PROP_POS_FRAMES, index)
            ret, frame = self.capture.read()
            if frame is not None:
                self.frame = frame.copy()
                self.refresh(frame)
            self.threadLock.release()

    def next_frame(self):
        if self.video_mode:
            self.threadLock.acquire()
            ret, frame = self.capture.read()
            if frame is not None:
                self.frame = frame.copy()
                self.refresh(frame)
            self.threadLock.release()

    def refresh(self, frame):
        if self.linecoor is not None:
            cv2.line(frame, (self.linecoor[0], 0), (self.linecoor[0], self.hight), (0, 0, 0))
            cv2.line(frame, (0, self.linecoor[1]), (self.width, self.linecoor[1]), (0, 0, 0))
        for rect in self.rects:
            cv2.rectangle(frame, (rect[0], rect[1]), (rect[2], rect[3]), (0, 0, 255), 2)
        if self.now_rect is not None:
            cv2.rectangle(frame, (self.now_rect[0], self.now_rect[1]), (self.now_rect[2], self.now_rect[3]),
                          (0, 255, 255), 2)
        frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2RGB)
        img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
        self.label.setPixmap(QPixmap.fromImage(img))
        self.admin.getUI(video_ui).set_frame_id(self.capture.get(cv2.CAP_PROP_POS_FRAMES))

    def loop(self):
        if (self.capture is not None) and (self.label is not None):
            t1 = time.time()
            self.threadLock.acquire()
            ret, frame = self.capture.read()
            self.threadLock.release()
            if frame is not None:
                self.threadLock.acquire()
                self.frame = frame.copy()
                self.threadLock.release()
                if self.linecoor is not None:
                    cv2.line(frame, (self.linecoor[0], 0), (self.linecoor[0], self.hight), (100, 100, 100))
                    cv2.line(frame, (0, self.linecoor[1]), (self.width, self.linecoor[1]), (100, 100, 100))
                for rect in self.rects:
                    cv2.rectangle(frame, (rect[0], rect[1]), (rect[2], rect[3]), (0, 0, 255), 2)
                if self.now_rect is not None:
                    cv2.rectangle(frame, (self.now_rect[0], self.now_rect[1]), (self.now_rect[2], self.now_rect[3]),
                                  (0, 255, 255), 2)
                frame = cv2.cvtColor(frame, cv2.COLOR_BGRA2RGB)
                # self.capture.read()
                img = QImage(frame.data, frame.shape[1], frame.shape[0], QImage.Format_RGB888)
                self.threadLock.acquire()
                self.label.setPixmap(QPixmap.fromImage(img))
                self.threadLock.release()
                if self.video_mode:
                    self.admin.getUI(video_ui).set_frame_id(self.capture.get(cv2.CAP_PROP_POS_FRAMES))
            t2 = time.time()
            t = (1 / self.fps) - (t2 - t1)
            if t > 0:
                time.sleep(t)
